package org.example.project.common.middleware.service.redis;

import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.script.RedisScript;

import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author wenxy
 * @date 2020/10/9
 */
public interface RedisBaseService<K, V> {

    /**
     * Determine if given {@code key} exists.
     *
     * @param key key
     * @return
     */
    Boolean hasKey(K key);

    /**
     * Delete given {@code keys}.
     *
     * @param keys keys
     * @return
     */
    Long delete(Collection<K> keys);

    /**
     * Unlink the {@code keys} from the key space
     *
     * @param keys keys
     * @return
     */
    Long unlink(Collection<K> keys);

    /**
     * Determine the type stored at {@code key}.
     *
     * @param key key
     * @return
     */
    String type(K key);

    /**
     * Set the expiration for given {@code key}
     *
     * @param key     key
     * @param timeout timeout
     * @return
     */
    Boolean expire(K key, Duration timeout);

    /**
     * Remove the expiration from given key
     *
     * @param key key
     * @return
     */
    Boolean persist(K key);

    /**
     * Get the time to live for {@code key}
     *
     * @param key      key
     * @param timeUnit
     * @return
     */
    Long getExpire(K key, TimeUnit timeUnit);

    /**
     * Request information and statistics about connected clients.
     *
     * @return
     */
    List<String> getClientListInfos();

    /**
     * Executes the given action object on a pipelined connection, returning the results. Note that the callback
     * <b>cannot</b> return a non-null value as it gets overwritten by the pipeline. This method will use the default
     * serializers to deserialize results
     *
     * @param action action
     * @return
     */
    List<Object> executePipelined(RedisCallback<?> action);

    /**
     * Executes the given {@link RedisScript}
     *
     * @param script The script to execute
     * @param keys   Any keys that need to be passed to the script
     * @param args   Any args that need to be passed to the script
     * @return The return value of the script or null if {@link RedisScript#getResultType()} is null, likely indicating a
     * throw-away status reply (i.e. "OK")
     */
    <T> T execute(RedisScript<T> script, List<K> keys, Object... args);
}
